module ad7928_driver #(
    parameter  AD7928_CHANNEL_NUM  = 4'd8, // MAX = 8 ��Ҫת����ͨ����
    parameter  AD7928_CHANNEL1_ADDR= 3'd0, //ͨ��1�ĵ�ַ
    parameter  AD7928_CHANNEL2_ADDR= 3'd1, //ͨ��2�ĵ�ַ
    parameter  AD7928_CHANNEL3_ADDR= 3'd2, //ͨ��3�ĵ�ַ
    parameter  AD7928_CHANNEL4_ADDR= 3'd3, //ͨ��4�ĵ�ַ
    parameter  AD7928_CHANNEL5_ADDR= 3'd4, //ͨ��5�ĵ�ַ
    parameter  AD7928_CHANNEL6_ADDR= 3'd5, //ͨ��6�ĵ�ַ
    parameter  AD7928_CHANNEL7_ADDR= 3'd6, //ͨ��7�ĵ�ַ
    parameter  AD7928_CHANNEL8_ADDR= 3'd7  //ͨ��8�ĵ�ַ
)(
    input                   sys_clk_i              ,
    input                   sys_rst_n_i             ,//��λ�͵�ƽ��Ч
    //�û��ӿ�
    input                   ad7928_convert_en_i     ,//�ߵ�ƽʱ��ʾ����ת��
    output                  ad7928_convert_ack_o    ,//ת������ź�
    output  [11:0]          ad7928_value0_o         ,
    output  [11:0]          ad7928_value1_o         ,
    output  [11:0]          ad7928_value2_o         ,
    output  [11:0]          ad7928_value3_o         ,
    output  [11:0]          ad7928_value4_o         ,
    output  [11:0]          ad7928_value5_o         ,
    output  [11:0]          ad7928_value6_o         ,
    output  [11:0]          ad7928_value7_o         ,
    //�����ӿ�
    output reg              ad7928_cs_pin_o         ,
    output reg              ad7928_sclk_pin_o       ,
    output reg              ad7928_mosi_pin_o       ,//оƬ����
    input                   ad7928_miso_pin_i        //оƬ�������
);
localparam WAIT_CNT = 8'd6;


reg  ad7928_drv_clk;
reg  ad7928_convert_ack;
reg  ad7928_convert_ack_d0;
reg  ad7928_convert_ack_d1;


wire ad7928_convert_en;
reg  ad7928_convert_en_r;  
reg  ad7928_convert_en_d0;
reg  ad7928_convert_en_d1;

wire [2:0] channels [7:0];
assign channels[0] = AD7928_CHANNEL1_ADDR;
assign channels[1] = AD7928_CHANNEL2_ADDR;
assign channels[2] = AD7928_CHANNEL3_ADDR;
assign channels[3] = AD7928_CHANNEL4_ADDR;
assign channels[4] = AD7928_CHANNEL5_ADDR;
assign channels[5] = AD7928_CHANNEL6_ADDR;
assign channels[6] = AD7928_CHANNEL7_ADDR;
assign channels[7] = AD7928_CHANNEL8_ADDR;

reg  [ 7:0] cnt;
reg  [ 2:0] idx;
reg  [ 2:0] addr;
reg  [11:0] wshift;
reg         nfirst;
reg  [11:0] data_in_latch;
reg         sck_pre;
reg  [11:0] ad7928_value [7:0];

assign ad7928_value0_o = ad7928_value[0];// ���ͨ��0ֵ
assign ad7928_value1_o = ad7928_value[1];// ���ͨ��1ֵ
assign ad7928_value2_o = ad7928_value[2];// ���ͨ��2ֵ
assign ad7928_value3_o = ad7928_value[3];// ���ͨ��3ֵ
assign ad7928_value4_o = ad7928_value[4];// ���ͨ��4ֵ
assign ad7928_value5_o = ad7928_value[5];// ���ͨ��5ֵ
assign ad7928_value6_o = ad7928_value[6];// ���ͨ��6ֵ
assign ad7928_value7_o = ad7928_value[7];// ���ͨ��7ֵ

assign ad7928_convert_ack_o = ( ~ad7928_convert_ack_d0) & ad7928_convert_ack_d1;
assign ad7928_convert_en    = ((~ad7928_convert_en_d0) & ad7928_convert_en_d1 ) ||
                              ((~ad7928_convert_en_d1) & ad7928_convert_en_d0 );

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        ad7928_drv_clk <= 1'b1;
    else
        ad7928_drv_clk <= ~ad7928_drv_clk;
end




always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) 
        ad7928_convert_en_r <= 1'b0;
    else if( ad7928_convert_en_i == 1'b1 )
        ad7928_convert_en_r <= ~ad7928_convert_en_r;
    else 
        ad7928_convert_en_r <= ad7928_convert_en_r;
end

always@( posedge ad7928_drv_clk or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        ad7928_convert_en_d0 <= 1'b0;
        ad7928_convert_en_d1 <= 1'b0;
    end
    else begin
        ad7928_convert_en_d0 <= ad7928_convert_en_r;
        ad7928_convert_en_d1 <= ad7928_convert_en_d0;
    end
end





// SPIʱ������
always @ (posedge ad7928_drv_clk or negedge sys_rst_n_i)
    if(~sys_rst_n_i)
        ad7928_sclk_pin_o <= 1'b1; // ��λʱSCLKΪ��
    else
        ad7928_sclk_pin_o <= sck_pre; // ��������ʱ����SCLK

// ��״̬��
always @ (posedge ad7928_drv_clk or negedge sys_rst_n_i)
    if(~sys_rst_n_i) begin
        cnt <= 0; // ��������λ
        idx <= 3'd7; // ��ʼ����
        addr <= 3'd0; // ��ʼ��ַ
        wshift <= 12'hFFF; // д��λ�Ĵ�����ֵ
        {ad7928_cs_pin_o, sck_pre, ad7928_mosi_pin_o} <= 3'b111; // ��ʼ���ź�
    end else begin
        if(cnt==8'd0) begin
            {ad7928_cs_pin_o, sck_pre, ad7928_mosi_pin_o} <= 3'b111; // Ƭѡ�źŸ�
            if(idx != 3'd0) begin
                cnt <= 8'd1; // ������һ��״̬
                idx <= idx - 3'd1; // �����ݼ�
            end else if(ad7928_convert_en) begin
                cnt <= 8'd1; // ������һ��״̬
                idx <= AD7928_CHANNEL_NUM; // ������Ϊͨ����
            end
        end else if(cnt==8'd1) begin
            {ad7928_cs_pin_o, sck_pre, ad7928_mosi_pin_o} <= 3'b111; // Ƭѡ�źŸ�
            addr <= (idx == 3'd0) ? AD7928_CHANNEL_NUM : idx - 3'd1; // ���õ�ַ
            cnt <= cnt + 8'd1; // ��������һ
        end else if(cnt==8'd2) begin
            {ad7928_cs_pin_o, sck_pre, ad7928_mosi_pin_o} <= 3'b111; // Ƭѡ�źŸ�
            wshift <= {1'b1, 1'b0, 1'b0, channels[addr], 2'b11, 1'b0, 1'b0, 2'b11}; // ����д��λ�Ĵ���
            cnt <= cnt + 8'd1; // ��������һ
        end else if(cnt<WAIT_CNT) begin
            {ad7928_cs_pin_o, sck_pre, ad7928_mosi_pin_o} <= 3'b111; // Ƭѡ�źŸ�
            cnt <= cnt + 8'd1; // ��������һ
        end else if(cnt<WAIT_CNT+8'd32) begin
            ad7928_cs_pin_o <= 1'b0; // Ƭѡ�źŵ�
            sck_pre <= ~sck_pre; // �л�ʱ��״̬
            if(sck_pre)
                {ad7928_mosi_pin_o,wshift} <= {wshift,1'b1}; // ��������
            cnt <= cnt + 8'd1; // ��������һ
        end else begin
            ad7928_cs_pin_o <= 1'b0; // Ƭѡ�źŵ�
            {sck_pre, ad7928_mosi_pin_o} <= 2'b11; // SCK��MOSi״̬
            cnt <= 8'd0; // ��������λ
        end
    end

// ���ݽ��մ���
always @ (posedge ad7928_drv_clk or negedge sys_rst_n_i)
    if(~sys_rst_n_i) begin
        ad7928_convert_ack <= 1'b0; // ת������źŸ�λ
        nfirst <= 1'b0; // �Ƿ�Ϊ��һ�ν������ݱ�־��λ
        data_in_latch <= 12'd0; // �����������渴λ
        ad7928_value[0] <= 12'd0; // ��ʼ���������ֵ
        ad7928_value[0] <= 12'd0;
        ad7928_value[1] <= 12'd0;
        ad7928_value[2] <= 12'd0;
        ad7928_value[3] <= 12'd0;
        ad7928_value[4] <= 12'd0;
        ad7928_value[5] <= 12'd0;
        ad7928_value[6] <= 12'd0;
        ad7928_value[7] <= 12'd0;
    end else begin
        ad7928_convert_ack <= 1'b0; // ת������źŸ�λ
        if(cnt>=WAIT_CNT+8'd2 && cnt<WAIT_CNT+8'd32) begin
            if(ad7928_sclk_pin_o)
                data_in_latch <= {data_in_latch[10:0], ad7928_miso_pin_i};// ��λ��������
        end else if(cnt==WAIT_CNT+8'd32) begin
            if(idx == 3'd0) begin
                nfirst <= 1'b1; // ���õ�һ�α�־
                ad7928_convert_ack <= 1'b1;//nfirst; // ����ת������ź�
            end
            ad7928_value[idx] <= data_in_latch; // �������ֵ
        end
    end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        ad7928_convert_ack_d0 <= 1'b0;
        ad7928_convert_ack_d1 <= 1'b0;
    end
    else begin
        ad7928_convert_ack_d0 <= ad7928_convert_ack;
        ad7928_convert_ack_d1 <= ad7928_convert_ack_d0;
    end
end
endmodule

